package demo.cglib.csdndemo;

import java.lang.reflect.Method;

import org.junit.Test;

import junit.framework.Assert;
import net.sf.cglib.beans.BeanCopier;
import net.sf.cglib.beans.BeanGenerator;
import net.sf.cglib.beans.ImmutableBean;
import net.sf.cglib.proxy.CallbackHelper;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.FixedValue;
import net.sf.cglib.proxy.InvocationHandler;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import net.sf.cglib.proxy.NoOp;


/**
 * http://blog.csdn.net/danchu/article/details/70238002
 * @author Wxg
 *
 */
public class SampleClass {

	public void test(){
		System.out.println("hello world");
	}
	
	public String test2(String input){
		return "hello world";
	}
	
	public static void main(String[] args) {
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(SampleClass.class);
		enhancer.setCallback(new MethodInterceptor() {
			@Override
			public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
				System.out.println("===before method run...");
				Object result = proxy.invokeSuper(obj, args);
				System.out.println("===after  method run...");
				return result;
			}
		});
		SampleClass sample = (SampleClass)enhancer.create();
		sample.test();
	}
	
	@Test
	public void testFixedValue(){
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(SampleClass.class);
		enhancer.setCallback(new FixedValue() {
			@Override
			public Object loadObject() throws Exception {
				return "Hello cglib";
			}
		});
		SampleClass proxy = (SampleClass)enhancer.create();
		System.out.println(proxy.test2(null));
		System.out.println(proxy.toString());
		System.out.println(proxy.getClass());
		System.out.println(proxy.hashCode());
	}
	
	@Test
	public void testInvocationHandler() throws Exception{
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(SampleClass.class);
		enhancer.setCallback(new InvocationHandler() {
			@Override
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
				if(method.getDeclaringClass() != Object.class && method.getReturnType() == String.class){
					return "--hello cglib";
				}else{
					throw new RuntimeException("Don't know what to do");
				}
			}
		});
		SampleClass proxy = (SampleClass)enhancer.create();
		Assert.assertEquals("--hello cglib", proxy.test2(null));
		System.out.println( proxy.toString() );
	}
	
	@Test
	public void testCallbackFilter() throws Exception{
		Enhancer enhancer = new Enhancer();
		CallbackHelper callbackHelper = new CallbackHelper(SampleClass.class, new Class[0]) {
			@Override
			protected Object getCallback(Method method) {
				if(method.getDeclaringClass() != Object.class && method.getReturnType() == String.class){
					return new FixedValue() {
						@Override
						public Object loadObject() throws Exception {
							return "Hello cglib";
						}
					};
				}else{
					return NoOp.INSTANCE;
				}
			}
		};
		enhancer.setSuperclass(SampleClass.class);
		enhancer.setCallbackFilter(callbackHelper);
		enhancer.setCallbacks(callbackHelper.getCallbacks());
		
		SampleClass proxy = (SampleClass)enhancer.create();
		System.out.println( proxy.test2(null) );
		System.out.println( proxy.toString() );
		System.out.println( proxy.hashCode() );
	}
	
	@Test(expected = IllegalStateException.class)
	public void testImmutableBean() throws Exception {
		SampleBean bean = new SampleBean();
		bean.setValue("Hello world");
		SampleBean immutableBean = (SampleBean) ImmutableBean.create(bean);
		System.out.println( immutableBean.getValue() );
		bean.setValue("hello world, again");
		System.out.println( immutableBean.getValue() );
		immutableBean.setValue("123");
	}
	
	@Test
	public void testBeanGenerator() throws Exception{
		BeanGenerator beanGenerator = new BeanGenerator();
		beanGenerator.addProperty("value", String.class);
		Object myBean = beanGenerator.create();
		Method setter = myBean.getClass().getMethod("setValue", String.class);
		setter.invoke(myBean, "Hello cglib");
		
		Method getter = myBean.getClass().getMethod("getValue");
		System.out.println( getter.invoke(myBean) );
	}
	
	@Test
	public void testBeanCopier() throws Exception {
		BeanCopier copier = BeanCopier.create(SampleBean.class, OtherSampleBean.class, false);
		SampleBean myBean = new SampleBean();
		myBean.setValue("==Hello,world==");
		OtherSampleBean otherBean = new OtherSampleBean();
		copier.copy(myBean, otherBean, null);
		System.out.println(otherBean.getValue());
	}
	
	
}
